﻿using SmartAnswerPlatform.Common;
using SmartAnswerPlatform.IRepository;
using SmartAnswerPlatform.Models.Entitys.Base;
using SmartAnswerPlatform.Models.ViewModels.Base;
using SqlSugar;
using System.Linq.Expressions;

namespace SmartAnswerPlatform.Repository
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : BaseEntity, new()
    {
        protected readonly ISqlSugarClient _db;

        public BaseRepository(ISqlSugarClient db)
        {
            _db = db;
        }

        public async Task<TEntity> FindById(string id)
        {
            return await _db.Queryable<TEntity>().Where(it => it.Id == id).SingleAsync();
        }

        public async Task<List<TEntity>> FindByIds(List<string> ids)
        {
            return await _db.Queryable<TEntity>().Where(it => ids.Contains(it.Id)).ToListAsync();
        }

        public async Task<List<TEntity>> FindAll()
        {
            return await _db.Queryable<TEntity>().ToListAsync();
        }

        public async Task<List<TEntity>> FindByWhere(Expression<Func<TEntity, bool>> expression)
        {
            return await _db.Queryable<TEntity>().Where(expression).ToListAsync();
        }

        public async Task<int> Update(TEntity entity)
        {
            updateSetBasicProperties(entity);
            return await _db.Updateable(entity).ExecuteCommandAsync();
        }

        public async Task<int> UpdateRange(List<TEntity> entities)
        {
            entities.ForEach(entity => updateSetBasicProperties(entity));
            return await _db.Updateable<TEntity>(entities).ExecuteCommandAsync();
        }

        public async Task<int> Delete(string id)
        {
            return await _db.Deleteable(new TEntity { Id = id }).ExecuteCommandAsync();
        }

        public async Task<int> DeleteRange(List<string> ids)
        {
            return await _db.Deleteable<TEntity>().Where(it => ids.Contains(it.Id)).ExecuteCommandAsync();
        }

        public async Task<TEntity> Insert(TEntity entity)
        {
            AddSetBasicProperties(entity);
            return await _db.Insertable<TEntity>(entity).ExecuteReturnEntityAsync();
        }

        public async Task<int> InsertRange(List<TEntity> entities)
        {
            entities.ForEach(entity => AddSetBasicProperties(entity));
            return await _db.Insertable<TEntity>(entities).ExecuteCommandAsync();
        }

        public void AddSetBasicProperties(TEntity entity)
        {
            entity.Id = IdGenerator.NextId();
            entity.CreateTime = DateTime.Now;
        }

        public void updateSetBasicProperties(TEntity entity)
        {
            entity.updateTime = DateTime.Now;
        }
    }
}
